﻿
using System;
using System.Diagnostics;
using System.Xml.Serialization;

namespace Nature
{
	
		
		
	
	/// <summary>
	/// Equivalence Ration (oxidizer–fuel ratio) [~]
	/// </summary>
	/// <remarks>
	/// wikipedia: Oxidizer–fuel ratio (OFR) is the mass ratio of oxidizer to fuel present in a reactive mixture. If exactly enough oxidizer is provided to completely burn all of the fuel, the ratio is known as the stoichiometric mixture, often abbreviated to stoich.
    /// </remarks>
	[DebuggerDisplay("{Value}")]
	public partial struct EquivalenceRatio : IEquatable<EquivalenceRatio>, IRoughlyEquatable<EquivalenceRatio>, IComparable<EquivalenceRatio>, IFormattable
	{
		/// <summary>
        /// Minimum possible value
        /// </summary>
		public const double MinValue = 0.0;
		
		/// <summary>
        /// Maximum possible value
        /// </summary>
		public const double MaxValue = double.PositiveInfinity;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private double? m_value;

		/// <summary>
        /// Initializes a new instance of the EquivalenceRatio data type to the given value
        /// </summary>
        /// <param name="value">EquivalenceRatio initializing value</param>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public EquivalenceRatio(double value) : this()
		{
			if( value < MinValue || value > MaxValue)
			{
				throw new System.ArgumentOutOfRangeException("value");
			}
			m_value = value;
		}

		/// <summary>
        /// Implicitly converts the EquivalenceRatio instance to the double presision value
        /// </summary>
        /// <param name="entity">EquivalenceRatio instance</param>
        /// <returns>Double presision representation of the EquivalenceRatio instance</returns>
		public static implicit operator double(EquivalenceRatio entity)
		{
			return entity.Value;
		}

		/// <summary>
        /// Creates nullable EquivalenceRatio object based on the given nullable double presision value
        /// </summary>
        /// <param name="v">Nullable double presision value</param>
        /// <returns>Nullable EquivalenceRatio object</returns>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public static EquivalenceRatio? Create(double? v)
		{
			if( v.HasValue ){ return new EquivalenceRatio(v.Value); }
			return new EquivalenceRatio?();
		}

		/// <summary>
		/// Gets the value of the current EquivalenceRatio value.
		/// </summary>
		public double Value
		{
			get
			{
				if( false == m_value.HasValue )
				{
					m_value = MinValue;
				}
				return m_value.Value;
			}
		}

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation.
        /// </summary>
		public override string ToString()
        {
            return Value.ToString();
        }

		/// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
		public override int GetHashCode()
        {
            return Value.GetHashCode();
        }	
       
		#region IEquatable<EquivalenceRatio> Members

		/// <summary>
        /// Indicates whether the current EquivalenceRatio instance is equal to another instance of the same type.
        /// </summary>
        /// <param name="other">An instance of the EquivalenceRatio type to compare with this instance.</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
        public bool Equals(EquivalenceRatio other)
        {
            return Value == other.Value;
        }

        #endregion

		#region IRoughlyEquatable<EquivalenceRatio,double> Members

		/// <summary>
        /// Indicates whether the current object is roughly equal to another object of the same type.
        /// </summary>
        /// <typeparam name="TTolerance">Generic tolerance type</typeparam>
        /// <param name="other">An EquivalenceRatio object to compare with this instance.</param>
        /// <param name="tolerance">A tolerance object determining the comparison accuracy</param>
        /// <returns>true if the current EquivalenceRatio object is roughly equal to the other parameter of the same type; otherwise, false.</returns>
        public bool IsSame<TTolerance>(EquivalenceRatio other, TTolerance tolerance) where TTolerance : ITolerance<double>
        {
            return tolerance.AreSame(this.Value, other.Value);
        }

        #endregion

		#region IComparable<EquivalenceRatio> Members

		/// <summary>
        /// Compares the current EquivalenceRatio instance with another object of the same type.
        /// </summary>
        /// <param name="other">An instance of the EquivalenceRatio type to compare with this object.</param>
        /// <returns>A value that indicates the relative order of the EquivalenceRatio instances being compared.
        /// The return value has the following meanings: Value Meaning Less than zero
        /// This object is less than the other parameter.Zero This object is equal to
        /// other. Greater than zero This object is greater than other.</returns>
        public int CompareTo(EquivalenceRatio other)
        {
            return Value.CompareTo(other.Value);
        }

        #endregion

		#region IFormattable Members

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information.
        /// </summary>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return Value.ToString(format, formatProvider);
        }

        #endregion

	}

		
	
	/// <summary>
	/// Mixture Fraction (Z) [~]
	/// </summary>
	/// <remarks>
	/// wikipedia: The mixture fraction measures the fuel/oxidizer ratio. It is normalized so Z=0 in the oxidizer stream and Z=1 in the fuel stream
    /// </remarks>
	[DebuggerDisplay("{Value}")]
	public partial struct MixtureFraction : IEquatable<MixtureFraction>, IRoughlyEquatable<MixtureFraction>, IComparable<MixtureFraction>, IFormattable
	{
		/// <summary>
        /// Minimum possible value
        /// </summary>
		public const double MinValue = 0.0;
		
		/// <summary>
        /// Maximum possible value
        /// </summary>
		public const double MaxValue = 1.0;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private double? m_value;

		/// <summary>
        /// Initializes a new instance of the MixtureFraction data type to the given value
        /// </summary>
        /// <param name="value">MixtureFraction initializing value</param>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public MixtureFraction(double value) : this()
		{
			if( value < MinValue || value > MaxValue)
			{
				throw new System.ArgumentOutOfRangeException("value");
			}
			m_value = value;
		}

		/// <summary>
        /// Implicitly converts the MixtureFraction instance to the double presision value
        /// </summary>
        /// <param name="entity">MixtureFraction instance</param>
        /// <returns>Double presision representation of the MixtureFraction instance</returns>
		public static implicit operator double(MixtureFraction entity)
		{
			return entity.Value;
		}

		/// <summary>
        /// Creates nullable MixtureFraction object based on the given nullable double presision value
        /// </summary>
        /// <param name="v">Nullable double presision value</param>
        /// <returns>Nullable MixtureFraction object</returns>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public static MixtureFraction? Create(double? v)
		{
			if( v.HasValue ){ return new MixtureFraction(v.Value); }
			return new MixtureFraction?();
		}

		/// <summary>
		/// Gets the value of the current MixtureFraction value.
		/// </summary>
		public double Value
		{
			get
			{
				if( false == m_value.HasValue )
				{
					m_value = MinValue;
				}
				return m_value.Value;
			}
		}

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation.
        /// </summary>
		public override string ToString()
        {
            return Value.ToString();
        }

		/// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
		public override int GetHashCode()
        {
            return Value.GetHashCode();
        }	
       
		#region IEquatable<MixtureFraction> Members

		/// <summary>
        /// Indicates whether the current MixtureFraction instance is equal to another instance of the same type.
        /// </summary>
        /// <param name="other">An instance of the MixtureFraction type to compare with this instance.</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
        public bool Equals(MixtureFraction other)
        {
            return Value == other.Value;
        }

        #endregion

		#region IRoughlyEquatable<MixtureFraction,double> Members

		/// <summary>
        /// Indicates whether the current object is roughly equal to another object of the same type.
        /// </summary>
        /// <typeparam name="TTolerance">Generic tolerance type</typeparam>
        /// <param name="other">An MixtureFraction object to compare with this instance.</param>
        /// <param name="tolerance">A tolerance object determining the comparison accuracy</param>
        /// <returns>true if the current MixtureFraction object is roughly equal to the other parameter of the same type; otherwise, false.</returns>
        public bool IsSame<TTolerance>(MixtureFraction other, TTolerance tolerance) where TTolerance : ITolerance<double>
        {
            return tolerance.AreSame(this.Value, other.Value);
        }

        #endregion

		#region IComparable<MixtureFraction> Members

		/// <summary>
        /// Compares the current MixtureFraction instance with another object of the same type.
        /// </summary>
        /// <param name="other">An instance of the MixtureFraction type to compare with this object.</param>
        /// <returns>A value that indicates the relative order of the MixtureFraction instances being compared.
        /// The return value has the following meanings: Value Meaning Less than zero
        /// This object is less than the other parameter.Zero This object is equal to
        /// other. Greater than zero This object is greater than other.</returns>
        public int CompareTo(MixtureFraction other)
        {
            return Value.CompareTo(other.Value);
        }

        #endregion

		#region IFormattable Members

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information.
        /// </summary>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return Value.ToString(format, formatProvider);
        }

        #endregion

	}

		
	
	/// <summary>
	/// Compression Ratio [~]
	/// </summary>
	/// <remarks>
	/// wikipedia: The compression ratio is a value that represents the ratio of the volume of its chamber from its largest capacity to its smallest capacity. It is a fundamental specification for many common combustion engines.
    /// </remarks>
	[DebuggerDisplay("{Value}")]
	public partial struct CompressionRatio : IEquatable<CompressionRatio>, IRoughlyEquatable<CompressionRatio>, IComparable<CompressionRatio>, IFormattable
	{
		/// <summary>
        /// Minimum possible value
        /// </summary>
		public const double MinValue = 0.0;
		
		/// <summary>
        /// Maximum possible value
        /// </summary>
		public const double MaxValue = double.PositiveInfinity;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private double? m_value;

		/// <summary>
        /// Initializes a new instance of the CompressionRatio data type to the given value
        /// </summary>
        /// <param name="value">CompressionRatio initializing value</param>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public CompressionRatio(double value) : this()
		{
			if( value < MinValue || value > MaxValue)
			{
				throw new System.ArgumentOutOfRangeException("value");
			}
			m_value = value;
		}

		/// <summary>
        /// Implicitly converts the CompressionRatio instance to the double presision value
        /// </summary>
        /// <param name="entity">CompressionRatio instance</param>
        /// <returns>Double presision representation of the CompressionRatio instance</returns>
		public static implicit operator double(CompressionRatio entity)
		{
			return entity.Value;
		}

		/// <summary>
        /// Creates nullable CompressionRatio object based on the given nullable double presision value
        /// </summary>
        /// <param name="v">Nullable double presision value</param>
        /// <returns>Nullable CompressionRatio object</returns>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public static CompressionRatio? Create(double? v)
		{
			if( v.HasValue ){ return new CompressionRatio(v.Value); }
			return new CompressionRatio?();
		}

		/// <summary>
		/// Gets the value of the current CompressionRatio value.
		/// </summary>
		public double Value
		{
			get
			{
				if( false == m_value.HasValue )
				{
					m_value = MinValue;
				}
				return m_value.Value;
			}
		}

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation.
        /// </summary>
		public override string ToString()
        {
            return Value.ToString();
        }

		/// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
		public override int GetHashCode()
        {
            return Value.GetHashCode();
        }	
       
		#region IEquatable<CompressionRatio> Members

		/// <summary>
        /// Indicates whether the current CompressionRatio instance is equal to another instance of the same type.
        /// </summary>
        /// <param name="other">An instance of the CompressionRatio type to compare with this instance.</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
        public bool Equals(CompressionRatio other)
        {
            return Value == other.Value;
        }

        #endregion

		#region IRoughlyEquatable<CompressionRatio,double> Members

		/// <summary>
        /// Indicates whether the current object is roughly equal to another object of the same type.
        /// </summary>
        /// <typeparam name="TTolerance">Generic tolerance type</typeparam>
        /// <param name="other">An CompressionRatio object to compare with this instance.</param>
        /// <param name="tolerance">A tolerance object determining the comparison accuracy</param>
        /// <returns>true if the current CompressionRatio object is roughly equal to the other parameter of the same type; otherwise, false.</returns>
        public bool IsSame<TTolerance>(CompressionRatio other, TTolerance tolerance) where TTolerance : ITolerance<double>
        {
            return tolerance.AreSame(this.Value, other.Value);
        }

        #endregion

		#region IComparable<CompressionRatio> Members

		/// <summary>
        /// Compares the current CompressionRatio instance with another object of the same type.
        /// </summary>
        /// <param name="other">An instance of the CompressionRatio type to compare with this object.</param>
        /// <returns>A value that indicates the relative order of the CompressionRatio instances being compared.
        /// The return value has the following meanings: Value Meaning Less than zero
        /// This object is less than the other parameter.Zero This object is equal to
        /// other. Greater than zero This object is greater than other.</returns>
        public int CompareTo(CompressionRatio other)
        {
            return Value.CompareTo(other.Value);
        }

        #endregion

		#region IFormattable Members

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information.
        /// </summary>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return Value.ToString(format, formatProvider);
        }

        #endregion

	}

		
	
	/// <summary>
	/// Mach Number (M = U / C) [~]
	/// </summary>
	/// <remarks>
	/// wikipedia: In fluid mechanics, Mach number (M) is a dimensionless number representing the speed of an object moving through gas or other fluid divided by the local speed of sound. It is commonly used to represent the speed of an object when it is traveling close to or above the speed of sound.
    /// </remarks>
	[DebuggerDisplay("{Value}")]
	public partial struct MachNumber : IEquatable<MachNumber>, IRoughlyEquatable<MachNumber>, IComparable<MachNumber>, IFormattable
	{
		/// <summary>
        /// Minimum possible value
        /// </summary>
		public const double MinValue = 0.0;
		
		/// <summary>
        /// Maximum possible value
        /// </summary>
		public const double MaxValue = double.PositiveInfinity;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private double? m_value;

		/// <summary>
        /// Initializes a new instance of the MachNumber data type to the given value
        /// </summary>
        /// <param name="value">MachNumber initializing value</param>
        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public MachNumber(double value) : this()
		{
			if( value < MinValue || value > MaxValue)
			{
				throw new System.ArgumentOutOfRangeException("value");
			}
			m_value = value;
		}

		/// <summary>
        /// Implicitly converts the MachNumber instance to the double presision value
        /// </summary>
        /// <param name="entity">MachNumber instance</param>
        /// <returns>Double presision representation of the MachNumber instance</returns>
		public static implicit operator double(MachNumber entity)
		{
			return entity.Value;
		}

		/// <summary>
        /// Creates nullable MachNumber object based on the given nullable double presision value
        /// </summary>
        /// <param name="v">Nullable double presision value</param>
        /// <returns>Nullable MachNumber object</returns>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
		public static MachNumber? Create(double? v)
		{
			if( v.HasValue ){ return new MachNumber(v.Value); }
			return new MachNumber?();
		}

		/// <summary>
		/// Gets the value of the current MachNumber value.
		/// </summary>
		public double Value
		{
			get
			{
				if( false == m_value.HasValue )
				{
					m_value = MinValue;
				}
				return m_value.Value;
			}
		}

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation.
        /// </summary>
		public override string ToString()
        {
            return Value.ToString();
        }

		/// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
		public override int GetHashCode()
        {
            return Value.GetHashCode();
        }	
       
		#region IEquatable<MachNumber> Members

		/// <summary>
        /// Indicates whether the current MachNumber instance is equal to another instance of the same type.
        /// </summary>
        /// <param name="other">An instance of the MachNumber type to compare with this instance.</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
        public bool Equals(MachNumber other)
        {
            return Value == other.Value;
        }

        #endregion

		#region IRoughlyEquatable<MachNumber,double> Members

		/// <summary>
        /// Indicates whether the current object is roughly equal to another object of the same type.
        /// </summary>
        /// <typeparam name="TTolerance">Generic tolerance type</typeparam>
        /// <param name="other">An MachNumber object to compare with this instance.</param>
        /// <param name="tolerance">A tolerance object determining the comparison accuracy</param>
        /// <returns>true if the current MachNumber object is roughly equal to the other parameter of the same type; otherwise, false.</returns>
        public bool IsSame<TTolerance>(MachNumber other, TTolerance tolerance) where TTolerance : ITolerance<double>
        {
            return tolerance.AreSame(this.Value, other.Value);
        }

        #endregion

		#region IComparable<MachNumber> Members

		/// <summary>
        /// Compares the current MachNumber instance with another object of the same type.
        /// </summary>
        /// <param name="other">An instance of the MachNumber type to compare with this object.</param>
        /// <returns>A value that indicates the relative order of the MachNumber instances being compared.
        /// The return value has the following meanings: Value Meaning Less than zero
        /// This object is less than the other parameter.Zero This object is equal to
        /// other. Greater than zero This object is greater than other.</returns>
        public int CompareTo(MachNumber other)
        {
            return Value.CompareTo(other.Value);
        }

        #endregion

		#region IFormattable Members

		/// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information.
        /// </summary>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return Value.ToString(format, formatProvider);
        }

        #endregion

	}

	
	
	/// <summary>
	/// Absolute tolerance
	/// </summary>
	[DebuggerDisplay("{Value}")]
    [Serializable]
    public struct DoubleAbsoluteTolerance : ITolerance<Double>
    {
		/// <summary>
        /// Gets the value
        /// </summary>
        public Double Value
        {
            get;
            private set;
        }

		/// <summary>
        /// Initializes a new instance of the DoubleAbsoluteTolerance structure
        /// </summary>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public DoubleAbsoluteTolerance(Double value) : this()
        {
            if (value < 0.0) { throw new System.ArgumentOutOfRangeException("value"); }
            this.Value = value;
        }

		/// <summary>
        /// Implicitly converts this Double instance into its double-presision type representation
        /// </summary>
        /// <param name="abstol">Absolute tolerance instance</param>
        /// <returns>double-presision type representation</returns>
		public static implicit operator Double(DoubleAbsoluteTolerance abstol) { return abstol.Value; }

		/// <summary>
        /// Compares two given values with the reduced accuracy determined by this Double value
        /// </summary>
        /// <param name="value1">First parameter</param>
        /// <param name="value2">Second parameter</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Double value1, Double value2)
		{
			Double absDiff = Math.Abs(value1 - value2);
			return absDiff < this.Value;
		}	
			
		/// <summary>
        /// Compares two given arrays of values based on the reduced accuracy determined by this instance
        /// </summary>
        /// <param name="array1">First array</param>
        /// <param name="array2">Second array</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Double[] array1, Double[] array2)			
		{
			Debug.Assert(array1.Length == array2.Length);
            for (int i = 0; i < array1.Length; ++i)
            {
                if (!this.AreSame(array1[i], array2[i])) { return false; }
            }
            return true;
		}
    }

	/// <summary>
	/// Relative tolerance
	/// </summary>
	[DebuggerDisplay("{Value}")]
    [Serializable]
    public struct DoubleRelativeTolerance : ITolerance<Double>
    {
		/// <summary>
        /// Gets the value
        /// </summary>
        public Double Value
        {
            get;
            private set;
        }

		/// <summary>
        /// Initializes a new instance of the DoubleRelativeTolerance structure
        /// </summary>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public DoubleRelativeTolerance(Double value) : this()
        {
            if (value < 0.0) { throw new ArgumentOutOfRangeException("value"); }
            this.Value = value;
        }

		/// <summary>
        /// Implicitly converts this Double instance into its double-presision type representation
        /// </summary>
        /// <param name="abstol">Relative tolerance instance</param>
        /// <returns>double-presision type representation</returns>
		public static implicit operator Double(DoubleRelativeTolerance reltol) { return reltol.Value; }

		/// <summary>
        /// Compares two given values with the reduced accuracy determined by this Double value
        /// </summary>
        /// <param name="value1">First parameter</param>
        /// <param name="value2">Second parameter</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Double value1, Double value2)
		{
			Double absDiff = Math.Abs(value1 - value2);
			Double averaged = ((Double)0.5) * (value1 + value2);
			Double delta = Math.Abs(averaged * this.Value);
			return absDiff <= delta;
		}		
			
		/// <summary>
        /// Compares two given arrays of values based on the reduced accuracy determined by this instance
        /// </summary>
        /// <param name="array1">First array</param>
        /// <param name="array2">Second array</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Double[] array1, Double[] array2)			
		{
			Debug.Assert(array1.Length == array2.Length);
            for (int i = 0; i < array1.Length; ++i)
            {
                if (!this.AreSame(array1[i], array2[i])) { return false; }
            }
            return true;
		}
			
		/// <summary>
        /// Calculates absolute relative difference between the two given parameters
        /// </summary>
        /// <param name="value1">First parameter</param>
        /// <param name="value2">Second parameter</param>
        /// <returns>Absolute relative difference</returns>
		public static Double AbsRelDiff(Double value1, Double value2)
		{
			Double absDiff = Math.Abs(value1 - value2);
			Double averaged = ((Double)0.5) * (value1 + value2);
			averaged = Math.Abs(averaged);
			averaged = Math.Max(Double.MinValue, averaged);
			return absDiff / averaged;
		}

    }

	/// <summary>
	/// Composite (absolute + relative) tolerance
	/// </summary>
    [Serializable]
	public class DoubleTolerance : ITolerance<Double>
	{				
		/// <summary>
		/// Initializes a new instance of the DoubleTolerance structure
		/// </summary>
		/// <param name="absTol">Absolute tolerance</param>
		/// <param name="relTol">Relative tolerance</param>
		public DoubleTolerance(Double absTol, Double relTol)
		{
			this.AbsoluteTolerance = new DoubleAbsoluteTolerance(absTol);
			this.RelativeTolerance = new DoubleRelativeTolerance(relTol);
		}
		
		/// <summary>
        /// Absolute olerance
        /// </summary>
		public DoubleAbsoluteTolerance AbsoluteTolerance
		{
			get;
			private set;
		}
			
		/// <summary>
        /// Relative tolerance
        /// </summary>
		public DoubleRelativeTolerance RelativeTolerance
		{
			get;
			private set;
		}
			
		public bool AreSame(Double value1, Double value2)
		{
			return 
				AbsoluteTolerance.AreSame(value1, value2) ||
				RelativeTolerance.AreSame(value1, value2);
		}	
		
		/// <summary>
        /// Compares two given arrays of values based on the reduced accuracy determined by this instance
        /// </summary>
        /// <param name="array1">First array</param>
        /// <param name="array2">Second array</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Double[] array1, Double[] array2)			
		{
			Debug.Assert(array1.Length == array2.Length);
            for (int i = 0; i < array1.Length; ++i)
            {
                if (!AbsoluteTolerance.AreSame(array1[i], array2[i]) &&
					!RelativeTolerance.AreSame(array1[i], array2[i])) 
				{ 
					return false; 
				}
            }
            return true;
		}				
	}
	
	public static partial class Extensions
	{
	    public static bool AreSame<TType>(this DoubleAbsoluteTolerance tolerance, TType a, TType b) 
            where TType : IRoughlyEquatable<TType, Double>
        {
            return a.IsSame(b, tolerance);
        }
			
		public static bool AreSame<TType>(this DoubleRelativeTolerance tolerance, TType a, TType b) 
            where TType : IRoughlyEquatable<TType, Double>
        {
            return a.IsSame(b, tolerance);
        }
			
		public static bool AreSame<TType>(this DoubleTolerance tolerance, TType a, TType b) 
            where TType : IRoughlyEquatable<TType, Double>
        {
            return a.IsSame(b, tolerance);
        }
	}
	
	
	/// <summary>
	/// Absolute tolerance
	/// </summary>
	[DebuggerDisplay("{Value}")]
    [Serializable]
    public struct SingleAbsoluteTolerance : ITolerance<Single>
    {
		/// <summary>
        /// Gets the value
        /// </summary>
        public Single Value
        {
            get;
            private set;
        }

		/// <summary>
        /// Initializes a new instance of the SingleAbsoluteTolerance structure
        /// </summary>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public SingleAbsoluteTolerance(Single value) : this()
        {
            if (value < 0.0) { throw new System.ArgumentOutOfRangeException("value"); }
            this.Value = value;
        }

		/// <summary>
        /// Implicitly converts this Single instance into its double-presision type representation
        /// </summary>
        /// <param name="abstol">Absolute tolerance instance</param>
        /// <returns>double-presision type representation</returns>
		public static implicit operator Single(SingleAbsoluteTolerance abstol) { return abstol.Value; }

		/// <summary>
        /// Compares two given values with the reduced accuracy determined by this Single value
        /// </summary>
        /// <param name="value1">First parameter</param>
        /// <param name="value2">Second parameter</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Single value1, Single value2)
		{
			Single absDiff = Math.Abs(value1 - value2);
			return absDiff < this.Value;
		}	
			
		/// <summary>
        /// Compares two given arrays of values based on the reduced accuracy determined by this instance
        /// </summary>
        /// <param name="array1">First array</param>
        /// <param name="array2">Second array</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Single[] array1, Single[] array2)			
		{
			Debug.Assert(array1.Length == array2.Length);
            for (int i = 0; i < array1.Length; ++i)
            {
                if (!this.AreSame(array1[i], array2[i])) { return false; }
            }
            return true;
		}
    }

	/// <summary>
	/// Relative tolerance
	/// </summary>
	[DebuggerDisplay("{Value}")]
    [Serializable]
    public struct SingleRelativeTolerance : ITolerance<Single>
    {
		/// <summary>
        /// Gets the value
        /// </summary>
        public Single Value
        {
            get;
            private set;
        }

		/// <summary>
        /// Initializes a new instance of the SingleRelativeTolerance structure
        /// </summary>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
        public SingleRelativeTolerance(Single value) : this()
        {
            if (value < 0.0) { throw new ArgumentOutOfRangeException("value"); }
            this.Value = value;
        }

		/// <summary>
        /// Implicitly converts this Single instance into its double-presision type representation
        /// </summary>
        /// <param name="abstol">Relative tolerance instance</param>
        /// <returns>double-presision type representation</returns>
		public static implicit operator Single(SingleRelativeTolerance reltol) { return reltol.Value; }

		/// <summary>
        /// Compares two given values with the reduced accuracy determined by this Single value
        /// </summary>
        /// <param name="value1">First parameter</param>
        /// <param name="value2">Second parameter</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Single value1, Single value2)
		{
			Single absDiff = Math.Abs(value1 - value2);
			Single averaged = ((Single)0.5) * (value1 + value2);
			Single delta = Math.Abs(averaged * this.Value);
			return absDiff <= delta;
		}		
			
		/// <summary>
        /// Compares two given arrays of values based on the reduced accuracy determined by this instance
        /// </summary>
        /// <param name="array1">First array</param>
        /// <param name="array2">Second array</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Single[] array1, Single[] array2)			
		{
			Debug.Assert(array1.Length == array2.Length);
            for (int i = 0; i < array1.Length; ++i)
            {
                if (!this.AreSame(array1[i], array2[i])) { return false; }
            }
            return true;
		}
			
		/// <summary>
        /// Calculates absolute relative difference between the two given parameters
        /// </summary>
        /// <param name="value1">First parameter</param>
        /// <param name="value2">Second parameter</param>
        /// <returns>Absolute relative difference</returns>
		public static Single AbsRelDiff(Single value1, Single value2)
		{
			Single absDiff = Math.Abs(value1 - value2);
			Single averaged = ((Single)0.5) * (value1 + value2);
			averaged = Math.Abs(averaged);
			averaged = Math.Max(Single.MinValue, averaged);
			return absDiff / averaged;
		}

    }

	/// <summary>
	/// Composite (absolute + relative) tolerance
	/// </summary>
    [Serializable]
	public class SingleTolerance : ITolerance<Single>
	{				
		/// <summary>
		/// Initializes a new instance of the SingleTolerance structure
		/// </summary>
		/// <param name="absTol">Absolute tolerance</param>
		/// <param name="relTol">Relative tolerance</param>
		public SingleTolerance(Single absTol, Single relTol)
		{
			this.AbsoluteTolerance = new SingleAbsoluteTolerance(absTol);
			this.RelativeTolerance = new SingleRelativeTolerance(relTol);
		}
		
		/// <summary>
        /// Absolute olerance
        /// </summary>
		public SingleAbsoluteTolerance AbsoluteTolerance
		{
			get;
			private set;
		}
			
		/// <summary>
        /// Relative tolerance
        /// </summary>
		public SingleRelativeTolerance RelativeTolerance
		{
			get;
			private set;
		}
			
		public bool AreSame(Single value1, Single value2)
		{
			return 
				AbsoluteTolerance.AreSame(value1, value2) ||
				RelativeTolerance.AreSame(value1, value2);
		}	
		
		/// <summary>
        /// Compares two given arrays of values based on the reduced accuracy determined by this instance
        /// </summary>
        /// <param name="array1">First array</param>
        /// <param name="array2">Second array</param>
        /// <returns>true if the current instance is equal to the other parameter; otherwise, false.</returns>
		public bool AreSame(Single[] array1, Single[] array2)			
		{
			Debug.Assert(array1.Length == array2.Length);
            for (int i = 0; i < array1.Length; ++i)
            {
                if (!AbsoluteTolerance.AreSame(array1[i], array2[i]) &&
					!RelativeTolerance.AreSame(array1[i], array2[i])) 
				{ 
					return false; 
				}
            }
            return true;
		}				
	}
	
	public static partial class Extensions
	{
	    public static bool AreSame<TType>(this SingleAbsoluteTolerance tolerance, TType a, TType b) 
            where TType : IRoughlyEquatable<TType, Single>
        {
            return a.IsSame(b, tolerance);
        }
			
		public static bool AreSame<TType>(this SingleRelativeTolerance tolerance, TType a, TType b) 
            where TType : IRoughlyEquatable<TType, Single>
        {
            return a.IsSame(b, tolerance);
        }
			
		public static bool AreSame<TType>(this SingleTolerance tolerance, TType a, TType b) 
            where TType : IRoughlyEquatable<TType, Single>
        {
            return a.IsSame(b, tolerance);
        }
	}
	
				
		
}
